import { CtlInput } from '../input/CtlInput'
import { parseYvanPropChangeVJson } from '../../CtlUtils'
import { CtlMultiComboDefault } from '../../CtlDefaultValue'
import { getFirstPinyin } from '../../Utils'
import { DataSource } from '../../YvanDataSource'
import { YvEvent, YvEventDispatch } from '../../YvanEvent'
import { YvDataSource } from '../../YvanDataSourceImp'

export class CtlMultiCombo extends CtlInput<CtlMultiCombo> {
  static create(module: any, vjson: any): CtlMultiCombo {
    const that = new CtlMultiCombo(vjson)
    that._module = module

    _.defaultsDeep(vjson, CtlMultiComboDefault)

    // 基础属性先执行
    that._create(vjson, that)

    const yvanProp = parseYvanPropChangeVJson(vjson, ['options', 'dataSource', 'onDataComplete', 'getRemoteData'])

    // 将 yvanProp 合并至当前 Ctl 对象
    _.assign(that, yvanProp)

    _.merge(vjson, that._webixConfig)

    return that
  }

  /**
   * 数据绑定完成后触发
   */
  onDataComplete?: YvEvent<CtlMultiCombo, any>

  /**
   * 获取远程数据触发
   */
  getRemoteData?: YvEvent<CtlMultiCombo, any>

  /**
   * 修改下拉选项
   */
  set options(nv: any[]) {
    const options: any = {
      filter(item: any, filterWord: string) {
        if (_.size(filterWord) <= 0) {
          return true
        }
        const nodePy = getFirstPinyin(item.text).toLowerCase()
        return (
          nodePy.indexOf(filterWord.toLowerCase()) >= 0 ||
          item.text.indexOf(filterWord) >= 0
        )
      },
      body: {
        template: '#text#',
        type: {
          height: 36
        },
        data: nv
      }
    }

    if (!this._webix) {
      _.merge(this._webixConfig, {
        view: 'multicombo',
        options
      })
      return
    }
    this._webix.define('options', options)
    this._webix.refresh()
  }

  /**
   * 修改下拉选项
   */
  set dataReal(nv: any[]) {
    this.options = nv
  }

  /**
   * 值分隔符
   */
  get separator(): string {
    if (!this._webix) {
      return this._webixConfig.separator
    }
    return this._webix.config['separator']
  }

  /**
   * 值分隔符
   */
  set separator(nv: string) {
    if (!this._webix) {
      this._webixConfig.separator = nv
    } else {
      this._webix.define('separator', nv)
    }
  }

  /**
   * 设置值 (如果不符合规定的格式 会清空)
   */
  set value(nv: any) {
    if (!this._webix) {
      this._webixConfig.value = nv
    } else {
      this._webix.setValue(nv)
    }
  }

  /**
   * 获取值(可能取到空值)
   */
  get value(): any {
    return this._webix.getValue()
  }

  /**
   * 获取显示的值
   */
  getText(): string {
    return this._webix.getText()
  }

  /**
   * 获取数据源设置
   */
  get dataSource(): DataSource<CtlMultiCombo> {
    return this._dataSource
  }

  /**
   * 设置数据源
   */
  set dataSource(nv: DataSource<CtlMultiCombo>) {
    this._dataSource = nv
    if (this._module.loadFinished) {
      // onLoad 之后会触发 view.onInited -> attachHandle -> refreshState -> _rebindDataSource
      // onLoad 之前都不需要主动触发 _rebindDataSource
      this._rebindDataSource()
    }
  }

  /* =============================================== 以下部分为私有函数 =============================================== */

  //数据源设置
  private _dataSource: DataSource<CtlMultiCombo>

  //数据源管理器
  private dataSourceBind?: YvDataSource<CtlMultiCombo>

  //重新绑定数据源
  private _rebindDataSource() {
    if (!this._module) {
      return;
    }

    const innerMethod = () => {
      if (this.dataSourceBind) {
        this.dataSourceBind.destory()
        this.dataSourceBind = undefined
      }

      if (this._webix && this._module) {
        this.dataSourceBind = new YvDataSource(this, this.dataSource, this._dataSourceProcess.bind(this))
        this.dataSourceBind.init()
      }
    }

    if (!this._module.loadFinished) {
      // onload 函数还没有执行（模块还没加载完）, 延迟调用 rebind
      _.defer(innerMethod)

    } else {
      // 否则实时调用 rebind
      innerMethod()
    }
  }

  private _dataSourceProcess(data: any[]) {
    if (
        !this.dataSource ||
        _.isArray(this.dataSource) ||
        _.isFunction(this.dataSource)
    ) {
      YvEventDispatch(this.getRemoteData, this, data)
      return data
    }

    if (this.dataSource.type !== 'SQL') {
      YvEventDispatch(this.getRemoteData, this, data)
      return data
    }

    const displayField = this.dataSource.displayField || 'text'
    const valueField = this.dataSource.valueField || 'id'
    const remoteData = _.map(data, item => {
      return {
        id: item[valueField],
        text: item[displayField]
      }
    })
    YvEventDispatch(this.getRemoteData, this, remoteData)
    return remoteData
  }

  //刷新状态时，自动重绑数据源
  protected refreshState() {
    super.refreshState()
    this._rebindDataSource()
  }
}
